﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using RemotingInterfaces;

namespace Model.Adventure
{
    //used for both what types of damage a character deals, aswell as what types of resistances to damage a character have
    //the usage of the class is dual. It can be used as offensive damage stats or as defensive damage stats
    //for defensive the damage multipliers acts as a damage resistance, and the damage boni acts as a flat damage reduction
    //for defensive the base damage and modified damage doesn't make any sense
    
    //BETTER SOLUTION: DAMAGE IS AN ABSTRACT CLASS AND THEN MAKE TWO CLASSES THAT INHERITS FROM DAMAGE
    [Serializable]
    public class Damage : MarshalByRefObject, IDamage //physical + fire damage implemented
    {        
        private double _base_damage; //the amount of damage done, divided into types. always rounded down   
     
        //damage multipliers in %, physical damage is divided into slashing, piercing and bludgeoning.
        //the sum of all multipliers can exceed 100%
        private double _slashing_mul, _piercing_mul, _bludgeoning_mul, _fire_mul, _electrical_mul, _ice_mul,
            _acid_mul, _sonic_mul, _negative_energy_mul, _positive_energy_mul, _divine_mul, _arcane_mul, _poison_mul;

        //flat damage bonus
        private double _slashing_bonus, _piercing_bonus, _bludgeoning_bonus, _fire_bonus, _electrical_bonus,
            _ice_bonus, _acid_bonus, _sonic_bonus, _negative_energy_bonus, _positive_energy_bonus,
            _divine_bonus, _arcane_bonus, _poison_bonus;

        public Damage() { }

        public Damage(double damage)
        {
            _base_damage = damage < 0 ? 0 : damage;      
        }

        //damage before multipliers
        public double Base_Damage
        {
            get { return _base_damage; }
            set
            {
                _base_damage = value;
            }
        }

        //slashing damage dealt
        public double Slashing_Damage
        {
            get { return (int)(_base_damage * _slashing_mul); }
        }

        //slashing damage multiplier
        public double Slashing
        {
            get { return _slashing_mul; }
            set
            {
                _slashing_mul = value < 0 ? 0 : value;
            }
        }

        //slashing damage resistance
        public double Slashing_Damage_Bonus
        {
            get { return _slashing_bonus; }
            set
            {                
                _slashing_bonus = value;
            }
        }

        //PIERCING
        public double Piercing_Damage
        {
            get { return (int)(_base_damage * _piercing_mul); }
        }

        public double Piercing
        {
            get { return _piercing_mul; }
            set
            {
                _piercing_mul = value;
            }
        }

        public double Piercing_Damage_Bonus
        {
            get { return _piercing_bonus; }
            set
            {
                _piercing_bonus = value < 0 ? 0 : value;
            }
        }

        //BLUDGEONING
        public double Bludgeoning_Damage
        {
            get { return (int)(_base_damage * _bludgeoning_mul); }
        }

        public double Bludgeoning
        {
            get { return _bludgeoning_mul; }
            set
            {
                _bludgeoning_mul = value;
            }
        }

        public double Bludgeoning_Damage_Bonus
        {
            get { return _bludgeoning_bonus; }
            set
            {
                _bludgeoning_bonus = value < 0 ? 0 : value;
            }
        }

        //FIRE
        public double Fire_Damage
        {
            get { return (int)(_base_damage * _fire_mul); }
        }

        public double Fire
        {
            get { return _fire_mul; }
            set
            {
                _fire_mul = value < 0 ? 0 : value;
            }
        }

        public double Fire_Damage_Bonus
        {
            get { return _fire_bonus; }
            set
            {
                _fire_bonus = value;
            }
        }

        //ELECTRICAL
        public double Electrical_Damage
        {
            get { return (int)(_base_damage * _electrical_mul); }
        }

        public double Electrical
        {
            get { return _electrical_mul; }
            set
            {
                _electrical_mul = value;
            }
        }

        public double Elecrical_Damage_Bonus
        {
            get { return _electrical_bonus; }
            set
            {
                _electrical_bonus = value < 0 ? 0 : value;
            }
        }

        //ICE
        public double Ice_Damage
        {
            get { return (int)(_base_damage * _ice_mul); }
        }

        public double Ice
        {
            get { return _ice_mul; }
            set
            {
                _ice_mul = value;
            }
        }

        public double Ice_Damage_Bonus
        {
            get { return _ice_bonus; }
            set
            {
                _ice_bonus = value < 0 ? 0 : value;
            }
        }

        //ACID
        public double Acid_Damage
        {
            get { return (int)(_base_damage * _acid_mul); }
        }

        public double Acid
        {
            get { return _acid_mul; }
            set
            {
                _acid_mul = value;
            }
        }

        public double Acid_Damage_Bonus
        {
            get { return _acid_bonus; }
            set
            {
                _acid_bonus = value < 0 ? 0 : value;
            }
        }

        //SONIC
        public double Sonic_Damage
        {
            get { return (int)(_base_damage * _sonic_mul); }
        }

        public double Sonic
        {
            get { return _sonic_mul; }
            set
            {
                _sonic_mul = value;
            }
        }

        public double Sonic_Damage_Bonus
        {
            get { return _sonic_bonus; }
            set
            {
                _sonic_bonus = value < 0 ? 0 : value;
            }
        }

        //NEGATIVE
        public double Negative_Energy_Damage
        {
            get { return (int)(_base_damage * _negative_energy_mul); }
        }

        public double Negative_Energy
        {
            get { return _negative_energy_mul; }
            set
            {
                _negative_energy_mul = value;
            }
        }

        public double Negative_Energy_Damage_Bonus
        {
            get { return _negative_energy_bonus; }
            set
            {
                _negative_energy_bonus = value < 0 ? 0 : value;
            }
        }

        //POSITIVE
        public double Positive_Energy_Damage
        {
            get { return (int)(_base_damage * _positive_energy_mul); }
        }

        public double Positive_Energy
        {
            get { return _positive_energy_mul; }
            set
            {
                _positive_energy_mul = value;
            }
        }

        public double Positive_Energy_Damage_Bonus
        {
            get { return _positive_energy_bonus; }
            set
            {
                _positive_energy_bonus = value < 0 ? 0 : value;
            }
        }

        //DIVINE
        public double Divine_Damage
        {
            get { return (int)(_base_damage * _divine_mul); }
        }

        public double Divine
        {
            get { return _divine_mul; }
            set
            {
                _divine_mul = value;
            }
        }

        public double Divine_Damage_Bonus
        {
            get { return _divine_bonus; }
            set
            {
                _divine_bonus = value < 0 ? 0 : value;
            }
        }

        //ARCANE
        public double Arcane_Damage
        {
            get { return (int)(_base_damage * _arcane_mul); }
        }

        public double Arcane
        {
            get { return _arcane_mul; }
            set
            {
                _arcane_mul = value;
            }
        }

        public double Arcane_Damage_Bonus
        {
            get { return _arcane_bonus; }
            set
            {
                _arcane_bonus = value < 0 ? 0 : value;
            }
        }

        //POISON
        public double Poison_Damage
        {
            get { return (int)(_base_damage * _poison_mul); }
        }

        public double Poison
        {
            get { return _poison_mul; }
            set
            {
                _poison_mul = value;
            }
        }

        public double Poison_Damage_Bonus
        {
            get { return _poison_bonus; }
            set
            {
                _poison_bonus = value < 0 ? 0 : value;
            }
        }
/*
        public static Damage operator + (Damage dam1, Damage dam2)
        {
            Damage damage = new Damage(dam1.Base_Damage + dam2.Base_Damage);

            //PHYSICAL
            damage.Slashing = dam1.Slashing + dam2.Slashing;
            damage.Slashing_Damage_Bonus = dam1.Slashing_Damage_Bonus + dam2.Slashing_Damage_Bonus;
            damage.Piercing = dam1.Piercing + dam2.Piercing;
            damage.Piercing_Damage_Bonus = dam1.Piercing_Damage_Bonus + dam2.Piercing_Damage_Bonus;
            damage.Bludgeoning = dam1.Bludgeoning + dam2.Bludgeoning;
            damage.Bludgeoning_Damage_Bonus = dam1.Bludgeoning_Damage_Bonus + dam2.Bludgeoning_Damage_Bonus;            
            //OTHER
            damage.Fire = dam1.Fire + dam2.Fire;
            damage.Fire_Damage_Bonus = dam1.Fire_Damage_Bonus + dam2.Fire_Damage_Bonus;
            damage.Electrical = dam1.Electrical + dam2.Electrical;
            damage.Elecrical_Damage_Bonus = dam1.Elecrical_Damage_Bonus + dam2.Elecrical_Damage_Bonus;
            damage.Ice = dam1.Ice + dam2.Ice;
            damage.Ice_Damage_Bonus = dam1.Ice_Damage_Bonus + dam2.Ice_Damage_Bonus;
            damage.Acid = dam1.Acid + dam2.Acid;
            damage.Sonic = dam1.Sonic + dam2.Sonic;
            damage.Sonic_Damage_Bonus = dam1.Sonic_Damage_Bonus + dam2.Sonic_Damage_Bonus;
            damage.Negative_Energy = dam1.Negative_Energy + dam2.Negative_Energy;
            damage.Negative_Energy_Damage_Bonus = dam1.Negative_Energy_Damage_Bonus + dam2.Negative_Energy_Damage_Bonus;
            damage.Positive_Energy = dam1.Positive_Energy + dam2.Positive_Energy;
            damage.Positive_Energy_Damage_Bonus = dam1.Positive_Energy_Damage_Bonus + dam2.Positive_Energy_Damage_Bonus;
            damage.Divine = dam1.Divine + dam2.Divine;
            damage.Divine_Damage_Bonus = dam1.Divine_Damage_Bonus + dam2.Divine_Damage_Bonus;
            damage.Arcane = dam1.Arcane + dam2.Arcane;
            damage.Arcane_Damage_Bonus = dam1.Arcane_Damage_Bonus + dam2.Arcane_Damage_Bonus;
            damage.Poison = dam1.Poison + dam2.Poison;
            damage.Poison_Damage_Bonus = dam1.Poison_Damage_Bonus + dam2.Poison_Damage_Bonus;
            return damage;            
        }

        public static Damage operator - (Damage dam1, Damage dam2)
        {
            Damage damage = new Damage(dam1.Base_Damage - dam2.Base_Damage);

            //PHYSICAL
            damage.Slashing = dam1.Slashing - dam2.Slashing;
            damage.Slashing_Damage_Bonus = dam1.Slashing_Damage_Bonus - dam2.Slashing_Damage_Bonus;
            damage.Piercing = dam1.Piercing - dam2.Piercing;
            damage.Piercing_Damage_Bonus = dam1.Piercing_Damage_Bonus - dam2.Piercing_Damage_Bonus;
            damage.Bludgeoning = dam1.Bludgeoning - dam2.Bludgeoning;
            damage.Bludgeoning_Damage_Bonus = dam1.Bludgeoning_Damage_Bonus - dam2.Bludgeoning_Damage_Bonus;
            //OTHER
            damage.Fire = dam1.Fire - dam2.Fire;
            damage.Fire_Damage_Bonus = dam1.Fire_Damage_Bonus - dam2.Fire_Damage_Bonus;
            damage.Electrical = dam1.Electrical - dam2.Electrical;
            damage.Elecrical_Damage_Bonus = dam1.Elecrical_Damage_Bonus - dam2.Elecrical_Damage_Bonus;
            damage.Ice = dam1.Ice - dam2.Ice;
            damage.Ice_Damage_Bonus = dam1.Ice_Damage_Bonus - dam2.Ice_Damage_Bonus;
            damage.Acid = dam1.Acid - dam2.Acid;
            damage.Sonic = dam1.Sonic - dam2.Sonic;
            damage.Sonic_Damage_Bonus = dam1.Sonic_Damage_Bonus - dam2.Sonic_Damage_Bonus;
            damage.Negative_Energy = dam1.Negative_Energy - dam2.Negative_Energy;
            damage.Negative_Energy_Damage_Bonus = dam1.Negative_Energy_Damage_Bonus - dam2.Negative_Energy_Damage_Bonus;
            damage.Positive_Energy = dam1.Positive_Energy - dam2.Positive_Energy;
            damage.Positive_Energy_Damage_Bonus = dam1.Positive_Energy_Damage_Bonus - dam2.Positive_Energy_Damage_Bonus;
            damage.Divine = dam1.Divine - dam2.Divine;
            damage.Divine_Damage_Bonus = dam1.Divine_Damage_Bonus - dam2.Divine_Damage_Bonus;
            damage.Arcane = dam1.Arcane - dam2.Arcane;
            damage.Arcane_Damage_Bonus = dam1.Arcane_Damage_Bonus - dam2.Arcane_Damage_Bonus;
            damage.Poison = dam1.Poison - dam2.Poison;
            damage.Poison_Damage_Bonus = dam1.Poison_Damage_Bonus - dam2.Poison_Damage_Bonus;
            return damage;
        }
*/
        public override string ToString()
        {
            String str = "";
            str +=  "Base damage = " + _base_damage + "\n" +
                    "Slashing = " + _slashing_mul * 100 + "%\n";
            return str;
        }
    }
}
